# asterisk-from-proxy.pm
# Copyright (C) 2006  Stephane Alnet
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# 

# This file is part of the CarrierClass.net project.
# For more information: http://carrierclass.net/
#
package CCNv2::Provision::Asterisk::from_proxy;
use strict;
use warnings;
use base qw(CCNCore::Provision::Base);
use CCNv2::Parameters;
use CCN::Text;
use CCNCore::Scripting;

sub run()
{
    my $self = shift;
    return unless defined $self->p->{cp_cluster};

    my $EIDLEN = $CCNv2::Parameters::eidlen;
    my $TIDLEN = $CCNv2::Parameters::tidlen;

    my $EIDPAT = CCNv2::Parameters::enterprise_pattern;
    my $TIDPAT = CCNv2::Parameters::trunk_pattern;

    my $LEN_TRUNK = 3+1+$TIDLEN+1;

    my $LEN_ENT  = 1+$EIDLEN;
    my $LEN_VME  = 3+$LEN_ENT+1;
    my $LEN_ELIN = 3+$LEN_ENT+1;

    # Note double-underscore in Asterisk variable names so that we can
    # pass them along with Dial(Local/...).

    my $vmpath = '/var/spool/asterisk/voicemail';
    
    my $from_proxy = copyright(';') . <<"EOT";
[from-proxy]
exten => i,1,Congestion()
exten => t,1,Congestion()
;
; Inbound calls from a phone.
;
; Called information
;
exten => _[*a-z0-9].,1,Noop
; PROXY and CALLEE are used for Emergency routing back to the phone
exten => _[*a-z0-9].,n,Set(__CALLEE=\${CALLERID(num)})
; These are all set by the proxy
exten => _[*a-z0-9].,n,Set(__PROXY=\${SIP_HEADER(X-CCN-PROXY)})
exten => _[*a-z0-9].,n,Set(__ENTERPRISE=\${SIP_HEADER(X-CCN-Enterprise)})
exten => _[*a-z0-9].,n,Set(CDR(userfield)=\${CALLEE})
exten => _[*a-z0-9].,n,Set(__POOL=\${SIP_HEADER(X-CCN-Pool)})
exten => _[*a-z0-9].,n,Set(__COS=\${SIP_HEADER(X-CCN-COS)})
exten => _[*a-z0-9].,n,Set(__CALLEE_EXTENSION=\${SIP_HEADER(X-CCN-Extension)})
exten => _[*a-z0-9].,n,Set(__SRC_IP=\${SIP_HEADER(X-CCN-SRCIP)})
;
; Save the original Called Party
exten => _[*a-z0-9].,n,Set(__CALLED=\${EXTEN})
;
exten => _[*a-z0-9].,n,Set(CALLERID(num)=\${CALLEE_EXTENSION})
exten => _[*a-z0-9].,n,Goto(\${POOL}-cos-\${COS},\${CALLED},1)
;
; Inbound calls to a phone (with treatment)
;
exten => _PHo${EIDPAT}m.,1,Noop
exten => _PHo${EIDPAT}m.,n,Set(__ENTERPRISE=\${EXTEN:3:$LEN_ENT})
exten => _PHo${EIDPAT}m.,n,Set(__CALLED=\${EXTEN:${LEN_VME}})
exten => _PHo${EIDPAT}m.,n,Goto(\${ENTERPRISE}-phones,\${CALLED},1)
;
;
; Inbound calls to voicemail (from a call-processing server)
;
exten => _VMb${EIDPAT}m.,1,Answer(1)
exten => _VMb${EIDPAT}m.,n,Set(ENTERPRISE=\${EXTEN:3:$LEN_ENT})
exten => _VMb${EIDPAT}m.,n,Set(CDR(userfield)=\${ENTERPRISE})
exten => _VMb${EIDPAT}m.,n,Set(EXTENSION=\${EXTEN:${LEN_VME}})
exten => _VMb${EIDPAT}m.,n,VoiceMail(b\${EXTENSION}\@\${ENTERPRISE})
exten => _VMb${EIDPAT}m.,n,Hangup
;
exten => _VMo${EIDPAT}m.,1,Answer(1)
exten => _VMo${EIDPAT}m.,n,Set(ENTERPRISE=\${EXTEN:3:$LEN_ENT})
exten => _VMo${EIDPAT}m.,n,Set(CDR(userfield)=\${ENTERPRISE})
exten => _VMo${EIDPAT}m.,n,Set(EXTENSION=\${EXTEN:${LEN_VME}})
exten => _VMo${EIDPAT}m.,n,VoiceMail(\${EXTENSION}\@\${ENTERPRISE})
exten => _VMo${EIDPAT}m.,n,Hangup
;
exten => _VMu${EIDPAT}m.,1,Answer(1)
exten => _VMu${EIDPAT}m.,n,Set(ENTERPRISE=\${EXTEN:3:$LEN_ENT})
exten => _VMu${EIDPAT}m.,n,Set(CDR(userfield)=\${ENTERPRISE})
exten => _VMu${EIDPAT}m.,n,Set(EXTENSION=\${EXTEN:${LEN_VME}})
exten => _VMu${EIDPAT}m.,n,VoiceMail(u\${EXTENSION}\@\${ENTERPRISE})
exten => _VMu${EIDPAT}m.,n,Hangup
;
exten => _VMm${EIDPAT}m.,1,Answer(1)
exten => _VMm${EIDPAT}m.,n,Set(ENTERPRISE=\${EXTEN:3:$LEN_ENT})
exten => _VMm${EIDPAT}m.,n,Set(CDR(userfield)=\${ENTERPRISE})
exten => _VMm${EIDPAT}m.,n,Set(EXTENSION=\${EXTEN:${LEN_VME}})
exten => _VMm${EIDPAT}m.,n,VoiceMailMain(\${EXTENSION}\@\${ENTERPRISE})
exten => _VMm${EIDPAT}m.,n,Hangup
;
exten => _VMs${EIDPAT}m.,1,Answer(1)
exten => _VMs${EIDPAT}m.,n,Set(ENTERPRISE=\${EXTEN:3:$LEN_ENT})
exten => _VMs${EIDPAT}m.,n,Set(CDR(userfield)=\${ENTERPRISE})
exten => _VMs${EIDPAT}m.,n,Set(EXTENSION=\${EXTEN:${LEN_VME}})
exten => _VMs${EIDPAT}m.,n,VoiceMailMain(s\${EXTENSION}\@\${ENTERPRISE})
exten => _VMs${EIDPAT}m.,n,Hangup
;
; Inbound calls from a third-party gateway
;
exten => _FTr${TIDPAT}m.,1,Set(TRUNK=\${EXTEN:3:${TIDLEN}})
exten => _FTr${TIDPAT}m.,2,Goto(route-from-trunk-\${TRUNK},\${EXTEN:${LEN_TRUNK}},1)
;
; Inbound calls towards a local trunk (zaptrunk, siptrunk)
;
exten => _TTr${TIDPAT}m.,1,Set(TRUNK=\${EXTEN:3:${TIDLEN}})
exten => _TTr${TIDPAT}m.,2,Goto(route-to-trunk-\${TRUNK},\${EXTEN:${LEN_TRUNK}},1)
;
; Erouter
;
; ERL -> ELIN selection (outbound calls)
;
; Note: ERl<enterprise-pk>l<erl-number>
;
exten => _ERl.,n,Set(ERL=\${EXTEN:3})
exten => _ERl.,n,Goto(erouter-erl,s,1)
;
; ELIN -> target mapping (inbound calls from PSAP)
;
; Note: ELi<enterprise-id>k<elin-number>
;
exten => _ELi${EIDPAT}k.,1,Set(ENTERPRISE=\${EXTEN:3:$LEN_ENT})
exten => _ELi${EIDPAT}k.,n,Set(CDR(userfield)=\${ENTERPRISE})
exten => _ELi${EIDPAT}k.,n,Set(ELIN=\${EXTEN:$LEN_ELIN})
exten => _ELi${EIDPAT}k.,n,Goto(erouter-elin,s,1)
;
EOT


    foreach('/etc/asterisk/config/extensions.from-proxy.conf')
    {
        CAT $_, $from_proxy;
        IF_CHANGED $_ => CCNv2::Scripting::AST('extensions reload');
    }


    # -------------- SIP entries for From-proxy --------------

    my $sip_proxy  = '';

    $self->sql_do_for( <<'SQL', $self->p->{cp_member},
        SELECT px_member, pk FROM server WHERE px_member IN 
            (SELECT px_cluster FROM cluster WHERE pk = ?)
SQL
    sub
    {
        my $proxy_cluster = shift;

        my $PROXY_pk = shift;
        my $PROXY_IP = $self->get_realtime_ip_of($PROXY_pk);
        my $PROXY_NAME = $self$self->p->make_server_name($PROXY_pk);

        $sip_proxy .= <<"EOT";
[${PROXY_NAME}]
type=friend
host=${PROXY_IP}
port=5060
outboundproxy=${PROXY_IP}
outboundproxyport=5060
; These are required for to-proxy to work (?)
username=
fromuser=
secret=
; NAT support not needed because the proxy takes care of it
nat=never
; YYY CanReINVITE needs more testing (especially wrt mediaproxy)
canreinvite=yes
;;; qualify=3000  ;;; YYY Stephane removed this because it creates timing issues
promiscredir=yes
rtpkeepalive=60
context=from-proxy
setvar=INBOUND_PX=${proxy_cluster}
setvar=PROXY_NAME=${PROXY_NAME}
setvar=PROXY_IP=${PROXY_IP}
;
; supported codecs
;
disallow=all
allow=ulaw
allow=alaw
allow=g729
;
EOT
    }); # for @proxy_clusters

    foreach('/etc/asterisk/config/sip.proxy.conf')
    {
        CAT $_, copyright(';') . $sip_proxy;
        IF_CHANGED $_ => CCNv2::Scripting::AST('sip reload');
    }
}
1;